/*
 * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

use crate::cli::ZipArgs;
use crate::error::ZipError;
use crate::utils::common::{apply_filters, copy_zip_file_to_zip, init_run_state, match_pattern};
use anyhow::Result;
use log::debug;
use std::path::PathBuf;

pub fn execute(args: &ZipArgs) -> Result<()> {
    let mut run_state = init_run_state(args)?;

    // 匹配模式列表
    let files_to_delete: Vec<String> = args
        .files
        .iter()
        .map(|p| p.to_string_lossy().to_string())
        .collect();

    if files_to_delete.is_empty() {
        return Err(
            ZipError::InvalidArguments("No files specified for deletion".to_string()).into(),
        );
    }

    let files_to_delete_map: std::collections::BTreeMap<String, PathBuf> = files_to_delete
        .iter()
        .map(|p| (p.to_string(), PathBuf::new()))
        .collect();
    run_state.init_display_info(&files_to_delete_map, &args.command)?;

    let mut deleted_count = 0;
    let mut kept_count = 0;

    let mut writer = run_state.writer.take().expect("Writer not initialized");
    let archive = run_state.archive.take().expect("Archive not initialized");

    // 遍历原zip中的所有文件
    for i in 0..archive.len() {
        let file = archive.by_index_raw(i)?;
        let name = file.name().to_string();

        // 检查是否在删除列表中
        let should_delete = files_to_delete
            .iter()
            .any(|pattern| match_pattern(&name, pattern, args.other.no_wildcards));

        if should_delete {
            if apply_filters(&name, args, true) {
                log::debug!("excluding : {}", name);
                if !args.basic_options.quiet && args.basic_options.verbose {
                    println!("excluding: {}", name);
                }
                kept_count += 1;
                // 这里是 kept_count，因为用户指定但被过滤掉了
                copy_zip_file_to_zip(&mut run_state, &file, &mut writer)?;
                continue;
            }
            run_state.update_display_info(writer.get_current_split_index(), file.compressed_size());
            run_state.print_operation_start("deleting", &name)?;
            run_state.print_operation_end_args(
                file.origin_size() as u64,
                file.compressed_size() as u64,
                file.compression_method(),
            );
            deleted_count += 1;
            continue; // 跳过此文件，不写入新zip
        }

        // 保留此文件
        if !args.basic_options.quiet {
            debug!("keeping: {}", name);
            kept_count += 1;
        }

        // 从原zip复制到新zip
        copy_zip_file_to_zip(&mut run_state, &file, &mut writer)?;
    }

    if archive.len() == kept_count {
        // 如果没有文件被删除，直接返回
        let zip_name = args.zipfile.clone().unwrap();
        return Err(ZipError::NothingToDo(zip_name.display().to_string()).into());
    }

    run_state.writer = Some(writer);
    run_state.archive = Some(archive);

    // 完成zip文件
    run_state.finish()?;

    if !args.basic_options.quiet {
        log::info!(
            "Success! Deleted {} files and keep {} files from {}",
            args.zipfile.clone().unwrap().display(),
            deleted_count,
            kept_count
        );
        if args.basic_options.verbose {
            run_state.print_summary_verbose();
        }
    }

    Ok(())
}
